package com.chen.q2.fibo;

import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.Semaphore;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.LockSupport;

public class FiboAdderRunnable implements Runnable {
    //计算结束标志
    private volatile boolean calFinish = false;

    private  Thread mainThread ;

    private Object lock;

    private Condition mainCondition;

    private Semaphore semaphore;

    private CountDownLatch countDownLatch;

    private CyclicBarrier cyclicBarrier;

    private final int toNum;

    private int result;


    public FiboAdderRunnable(int toNum) {
        this.toNum = toNum;
    }

    public  FiboAdderRunnable(int toNum,Object lock) {
        this.toNum = toNum;
        this.lock = lock;
    }

    private void sum() {
        int result = fibo(toNum);
        this.result = result;
        calFinish = true;
        if (lock!=null){
            synchronized (lock){
                lock.notifyAll();
            }
        }
        if (mainThread != null){
            LockSupport.unpark(mainThread);
        }
        if (mainCondition != null){
            Lock lock = (Lock)this.lock;
            lock.lock();
            try {
                mainCondition.signal();
            }finally {
                lock.unlock();
            }
        }
        if (semaphore != null){
            semaphore.release();
        }
        if (countDownLatch != null){
            countDownLatch.countDown();
        }
        if (cyclicBarrier!=null){
            try {
                cyclicBarrier.await();
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (BrokenBarrierException e) {
                e.printStackTrace();
            }
        }

    }

    private static int fibo(int a) {
        if ( a < 2){
            return 1;
        }
        return fibo(a-1) + fibo(a-2);
    }

    @Override
    public void run() {
        sum();
    }

    public int getResult(){
        return result;
    }

    public boolean getCalFinish(){
        return this.calFinish;
    }

    public void setMainThread(Thread thread){
        this.mainThread = thread;
    }

    public void setMainLockCondition(Lock lock,Condition mainCondition) {
        this.lock = lock;
        this.mainCondition = mainCondition;
    }

    public void setSemaphore(Semaphore semaphore) {
        this.semaphore = semaphore;
    }

    public void setCountDownLatch(CountDownLatch countDownLatch) {
        this.countDownLatch = countDownLatch;
    }

    public void setCyclicBarrier(CyclicBarrier cyclicBarrier) {
        this.cyclicBarrier = cyclicBarrier;
    }

}
